package example.demo.route.spi;

import example.demo.route.routerule.RouteRule;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Iterator;
import java.util.ServiceLoader;

/**
 * <? 方式二
 */
@Component
public class SpiFactoryBean implements FactoryBean<RouteRule> {
    @Value("${rao.table-sum:4}")
    int tableSum;

    @Override
    public RouteRule getObject() throws BeansException {
        ServiceLoader<RouteRule> routeRules = ServiceLoader.load(RouteRule.class);
        Iterator<RouteRule> iterator = routeRules.iterator();
        RouteRule next = iterator.next();
        next.setTableSum(tableSum);
        return next;
    }


    @Component
    static class SpiBean implements ApplicationContextAware,
            /*web容器启动*/
            ApplicationListener<ServletWebServerInitializedEvent> {
        ApplicationContext applicationContext;

        /**
         * di-succeed
         */
        @Autowired
        public SpiBean(RouteRule routeRule) {
            System.out.println(routeRule);
        }

        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            //我惊讶到了static class 可以使用this。。。
            this.applicationContext = applicationContext;
        }

        @Override
        public void onApplicationEvent(ServletWebServerInitializedEvent event) {
            Arrays.stream(applicationContext.getBeanDefinitionNames()).forEach(System.out::println);
        }
    }

    @Override
    public Class<RouteRule> getObjectType() {
        return RouteRule.class;
    }

    //单例
    @Override
    public boolean isSingleton() {
        return true;
    }
}
